跳至主要内容

SQL 做法、通靈


2020/4/7 王子軒


這堂課,補充一些東西,之後我們來應用一下你們之學的


這是之前的簡報

SELECT, UPDATE:https://hackmd.io/@XMRHRX/HJ-P95kGu#/
INSERT, DELETE, KEY:https://hackmd.io/@XMRHRX/rkKg-VfzO#/
INNER JOIN, UNION:https://hackmd.io/@XMRHRX/HyovPkEzd


語法的補充


AS

將某個欄位或是表設定一個別名(Alias)


WHERE with Alias


ORDER BY

SELECT <col1>[, <col2>...]
FROM <table>
ORDER BY <col> [<ASC|DESC>][, <col> [<ASC|DESC>]...]

ASC: 遞增 DESC:遞減 (如果沒有選擇,預設 ASC)


假設有一張表…


SELECT * FROM employees ORDER BY Title;

結果:


TOP (SQL Server)

LIMIT (MySQL)

ROWNUM (Oracle)

限制查詢後,最多顯示多少比資料


補充一些 table 的 column 設定


AUTO INCREMENT

欄位的值在插入時會自動增加(INCREMENT)

常常被用在作為 PK 的 ID,讓每筆資料的編號由資料庫系統幫你處理。


UNIQUE

欄位值不重複,如:生份證號碼


NOT NULL

設定該欄位不能為 NULL(類似空值),如:密碼


有 NOT NULL 和 AUTO_INCREMENT 的範例

建議需要時,再根據使用的資料庫系統上網查,因為語法時常有不同


SQL 的 function

要特別注意 function 會因為資料庫系統不同而有差 mysql、nosql、mariaDB…一大堆資料庫系統


SUM()

int SUM(int)

加總欄位的"數值"

SELECT SUM(<int col>) FROM table_name;
ex:
SELECT SUM(`city_code`) FROM Taiwan_City

範例


CONCAT

str CONCAT(str1, str2[, str3...])

合併"字串",將傳入的字串接起來


SLEEP()

睡覺

讓資料庫暫停/延遲/睡眠一段時間 聽起來沒用是吧?


COUNT()

int COUNT(<column_name>)

回傳該欄位總共有幾筆資料


試試

先下載&匯入:https://drive.google.com/file/d/1gKfOSMpdLPZgCxjxwGG8CCgmTdg8V9IL/view?usp=sharing


情境:新生入住

今天宿舍服務中心給了新生入住的表,

學號床位
B10700011G404-1
B10516005G405-1
B10716043G406-1

流程

  1. 根據入住資料的學號,從表 user 查到 uid
  2. 根據為床位,對應到 iptable 的 description
  3. 把 user 查到的 uid,填寫到 iptable 裡面的 uid

(實際情況跟練習有差)


學號床位
B10700011G404-1
B10516005G405-1
B10716043G406-1

試著用一個 query,只要放入對應的學號和床位,就能幫它入住。 下一頁有提示,要的自己翻頁過去 > <


流程

  1. 根據入住資料的學號,從表 user 查到 uid

    SELECT WHERE

  2. 根據為床位,對應到 iptable 的 description

    SELECT WHERE,善用LIKE %


  1. 把 user 查到的 uid,填寫到 iptable 裡面的 uid

    INNER JOIN, UPDATE

先試著正確的查詢 1,2 步驟,再來試著用 INNER JOIN,正確根據床位合併,最後再來 UPDATE


SQL 的安全問題

SQL 的重點:injection
講了 3 堂課就是為了這個

幹訓的簡報:https://hackmd.io/@XMRHRX/rkFX8pLuv#/4/6


幹訓的時候...SQL injection

NOTE:我知道幹訓的時候大部分人一臉蒙逼,在完全不知道 SQL 也沒寫過查詢就直接學注入 XD。


看懂 SQL 了,再回頭看一次

假設我們用查到的數量判斷,判斷帳號是否存在
SELECT COUNT(*) FROM `user`
WHERE `username` = "<user input>"

NOTE:就是如果你輸入的判斷查到資料,COUNT 就不會是 0,如果你輸入得資料不再資料庫內,就會是 0


user input = B10811011

SELECT COUNT(*) FROM `user`
WHERE `username` = "B10811011"


user input = B10811011" OR true --+-

SELECT COUNT(*) FROM `user`
WHERE `username` = "B10811011" OR true --+- "

--+-是 SQL 的註解之一,這裡是為了把最後一個\"無視,避免語法錯誤

NOTE: 這樣就可以破壞原來的用意,可以想想,既然可以插入自己的 query,那 query 還可以做哪些事情呢?


通常的學習軌跡
  1. 了解 SQL
  2. 寫過 SQL
  3. 程式裡面用過 SQL
  4. 被打爆
  5. 看懂攻擊原理
  6. 開幹

有興趣可以試著在程式裡應用資料庫 不管要搞開發還是要把別人的 Server 搞到開花 未來都會用到

NOTE:其實這才是通常的軌跡,雖然我也是從注入開始學的啦 XD


補充資料

互動式教學:https://www.hacksplaining.com/exercises/sql-injection
Lab:https://defendtheweb.net/playground?subject=sqli